package org.jeecg.common.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Scanner;

/**
 * @Classname ZzSecurityHelper
 * @Description TODO
 * @Date 2019/6/24 16:50
 * @Created by whd
 */ 
public class ZzSecurityHelper {
    /*
     * 加密用的Key 可以用26个字母和数字组成 使用AES-128-CBC加密模式，key需要为16位。
     */
    private static final String key="tw1nt0n3976ksiqp"; 
    private static final String iv ="T3897io0wint0n3o";  
    private static final String initVector = "T3897io0wint0n3o";

    private static String bytesToHex(byte[] bytes) {
        String hex = new BigInteger(1, bytes).toString(16);
        return hex;
    }
    public static byte hexToByte(String inHex){  
        return (byte)Integer.parseInt(inHex,16);  
    }  

    public static byte[] hexToByteArray(String inHex){  
        int hexlen = inHex.length();  
        byte[] result;  
        if (hexlen % 2 == 1){  
            //奇数  
            hexlen++;  
            result = new byte[(hexlen/2)];  
            inHex="0"+inHex;  
        }else {  
            //偶数  
            result = new byte[(hexlen/2)];  
        }  
        int j=0;  
        for (int i = 0; i < hexlen; i+=2){  
            result[j]=hexToByte(inHex.substring(i,i+2));  
            j++;  
        }  
        return result;   
    }  
    
    //加密
    public static String encrypt(String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            // return Base64.encodeBase64String(encrypted);
            return bytesToHex(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
    /**
     * @author miracle.qu
     * @Description AES算法加密明文
     * @param data 明文
     * @param key 密钥，长度16
     * @param iv 偏移量，长度16
     * @return 密文
     */
    public static String encryptAES(String data) throws Exception {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            int blockSize = cipher.getBlockSize();
            byte[] dataBytes = data.getBytes();
            int plaintextLength = dataBytes.length;
 
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }
 
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
 
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());  // CBC模式，需要一个向量iv，可增加加密算法的强度
 
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);
 
            return ZzSecurityHelper.encode(encrypted).trim(); // BASE64做转码。
 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
 
    /**
     * @author miracle.qu
     * @Description AES算法解密密文
     * @param data 密文
     * @param key 密钥，长度16
     * @param iv 偏移量，长度16
     * @return 明文
     */
    public static String decryptAES(String data) throws Exception {
        try
        {
             byte[] encrypted1 = ZzSecurityHelper.decode(data);//先用base64解密
//            byte[] encrypted1  = ZzSecurityHelper.hexToByteArray(data);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
 
            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
 
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString.trim();
        }
        catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 编码
     * @param byteArray
     * @return
     */
    public static String encode(byte[] byteArray) {
        return new String(new Base64().encode(byteArray));
    }
 
    /**
     * 解码
     * @param base64EncodedString
     * @return
     */
    public static byte[] decode(String base64EncodedString) {
        return new Base64().decode(base64EncodedString);
    }

    /**
    * 获取硬盘序列号
    *
    *
    * */
    private static String getWindowsSerialNumber() {
        String result = "";
        try {
            Process process = Runtime.getRuntime().exec(new String[] { "wmic", "diskdrive", "get", "serialnumber" });
            process.getOutputStream().close();
            Scanner scanner = new Scanner(process.getInputStream());
            scanner.next();
            result = scanner.next();
            scanner.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    private static String getUnixSerialNumber() {
        String result = "";
        try {
            Process process = Runtime.getRuntime().exec(new String[] { "udevadm", "info", "--query=all", "--name=/dev/sda" });
            process.getOutputStream().close();
            Scanner scanner = new Scanner(process.getInputStream());
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                if (line.contains("ID_SERIAL_SHORT")) {
                    result = line.split("=")[1].trim();
                    break;
                }
            }
            scanner.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String getSerialNumber() {
        String os = System.getProperty("os.name").toLowerCase();
        String Number = "";
        if (os.contains("win")) {
//            System.out.println("Serial Number: " + getWindowsSerialNumber());
            Number = getWindowsSerialNumber();
        } else if (os.contains("nix") || os.contains("nux") || os.indexOf("mac") != -1) {
//            System.out.println("Serial Number: " + getUnixSerialNumber());
            Number = getUnixSerialNumber();
        }
        return Number;
    }

    public static String getip(){
        InetAddress localhost = null;
        try {
            localhost = InetAddress.getLocalHost();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String ip = localhost.getHostAddress();
        return ip;
    }

    public static String gethostname(){
        InetAddress localhost = null;
        try {
            localhost = InetAddress.getLocalHost();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String ip = localhost.getHostName();
        return ip;
    }


}
